#pragma once
#include "common.h"
#include "color/truecolor.h"

namespace anip
{
    /// <summary>
    /// Represents a color system using three parameters and one alpha channel.
    /// The basic rule of ordering is that the 'standalone' controlling parameter 
    /// as would be in a color picker widget should come first. E.g. for CIELAB, 
    /// that would be lightness; for cyclindrical representations like HSV or LCh, 
    /// the  'argument' component should come first. (Yes, we actually use hLC 
    /// instead of LCh.)
    /// </summary>
    class TrivariateColorProvider
    {
    public:
        struct ComponentInfo
        {
            // This wouldn't need i18n, huh?
            wstring name;
            float min, max;
            bool 
                lbound = false, 
                rbound = false,
                warp = false;
        };

        /// <summary>
        /// Converts colors in this system into `TrueColor`s. Note: alpha channel included.
        /// Also note: implementors should handle the situation when buffer == out
        /// </summary>
        virtual void toTrueColor(
            const float* buffer, TrueColor* out, size_t n = 1) const = 0;

        /// <summary>
        /// Converts `TrueColor`s into colors in this system. Note: alpha channel included.
        /// Also note: implementors should handle the situation when buffer == out
        /// </summary>
        virtual void fromTrueColor(
            const TrueColor* buffer, float* out, size_t n = 1) const = 0;

        virtual ComponentInfo first() const = 0;
        virtual ComponentInfo second() const = 0;
        virtual ComponentInfo third() const = 0;

        static const TrivariateColorProvider
            * sRGB, * HSV,
            * CIELAB, * CIEhLC, * CIEhLS;
    };
}